package com.atguigu.order.exception;
import com.alibaba.csp.sentinel.adapter.spring.webmvc_v6x.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.atguigu.common.R;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;

import java.io.PrintWriter;
/**
 * 自定义的Block异常处理器
 * 用于处理Sentinel中定义的资源被限流或降级时的异常情况
 * 实现了BlockExceptionHandler接口，以覆盖默认的异常处理行为
 */
@Component
public class MyBlockExceptionHandler implements BlockExceptionHandler {
    // 使用ObjectMapper将自定义的错误信息转换为JSON格式
    private ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 处理限流或降级异常的方法
     *
     * @param request HTTP请求对象，包含请求的相关信息
     * @param response HTTP响应对象，用于向客户端发送响应
     * @param resourceName 被限流或降级的资源名称
     * @param e 触发的Block异常实例，包含限流或降级的具体原因
     * @throws Exception 可能抛出的异常
     */
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, String resourceName, BlockException e) throws Exception {
       response.setStatus(429);
        // 设置响应内容类型为JSON，并指定字符集为UTF-8
        response.setContentType("application/json;charset=UTF-8");
        // 获取响应的输出流，用于写入JSON格式的错误信息
        PrintWriter writer = response.getWriter();
        // 创建错误信息对象，包含错误码和资源被限流或降级的原因
        R error = R.error(500, resourceName + " 被Sentinel限制了，原因是: " + e.getClass());
        // 将错误信息对象转换为JSON字符串
        String json = objectMapper.writeValueAsString(error);
        // 将JSON字符串写入响应中
        writer.write(json);
        // 刷新输出流，确保数据被写出
        writer.flush();
        // 关闭输出流
        writer.close();
    }
}

